package de.akabahn.ebd.control;

import java.io.PrintWriter;
import java.io.StringWriter;

import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.Color;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import de.akabahn.ebd.control.auth.AbstractAuthenticator;
import de.akabahn.ebd.control.auth.RemoteAuthenticator;
import de.akabahn.ebd.control.auth.StaticAuthenticator;
import de.akabahn.ebd.control.auth.UserAuthObject;
import de.akabahn.ebd.control.data.DebugDataContainer;

/**
 * @author Christian Schlehuber
 * @author Peter Eimann
 * @since 0.1
 * @version 0.2
 */
public class EBD_LoginActivity extends Activity {

	private AbstractAuthenticator authenticator;
	private DebugDataContainer ddc;
	private SharedPreferences preferences;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

        Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread paramThread, Throwable exception) {
                StringWriter stackTrace = new StringWriter();
                exception.printStackTrace(new PrintWriter(stackTrace));

                StringBuilder errormessage = new StringBuilder(exception.getMessage());
            	while (exception.getCause() != null) {
            		exception = exception.getCause();
            		errormessage.append("\n\t\t- ").append(exception.getMessage());
            	}

                Intent loginIntent = new Intent(EBD_LoginActivity.this, EBD_LoginActivity.class);
                loginIntent.putExtra("de.akabahn.ebd.control.errormessage", errormessage.toString());
                loginIntent.putExtra("de.akabahn.ebd.control.stacktrace", stackTrace.toString());
                loginIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
                loginIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                startActivity(loginIntent);
                System.exit(0);
            }
        });

        ddc = DebugDataContainer.getInstance();
        setContentView(R.layout.login);
		PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
		preferences = PreferenceManager.getDefaultSharedPreferences(this);

		Button proceed = (Button) findViewById(R.id.login_login_button);
		proceed.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				Intent next = null;

				UserAuthObject user = checkCredentials();
				if (user == null) {
					Toast.makeText(EBD_LoginActivity.this,
							getResources().getString(R.string.login_invalidLogin), Toast.LENGTH_LONG).show();
					return;
				}

				try {
					PackageInfo pInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
					ddc.add("LoginActivity", "Application version = " + pInfo.versionName);
					ddc.add("LoginActivity", "User version = " + user.getVersion());

					if (user.getVersion() != null 
							&& (getVersionAsNumber(user.getVersion()) > getVersionAsNumber(pInfo.versionName))) {
						Toast.makeText(EBD_LoginActivity.this, 
								getResources().getString(R.string.login_newVersion, user.getVersion()), 
								Toast.LENGTH_LONG).show();
					}
				} catch (NameNotFoundException e) {
					ddc.add("LoginActivity", "No version information: " + e.toString());
				}

				String bahnhof = ((Spinner)findViewById(R.id.login_spinner_bahnhof)).getSelectedItem().toString();
				int posNummer = bahnhof.indexOf('(');

				switch (user.getAccessRights()) {
					case RESTRICTED:
						if (bahnhof.startsWith("--")) {
							Toast.makeText(EBD_LoginActivity.this,
									getResources().getString(R.string.login_noBahnhof), Toast.LENGTH_LONG).show();
							return;
						}
						next = new Intent(v.getContext(), EBD_HandreglerActivity.class);
						break;
					case COMMON:
						next = new Intent(v.getContext(), EBD_HandreglerActivity.class);
						break;
					case ACTIVE:
					case TECHNICIAN:
						next = new Intent(v.getContext(), EBD_ChooseActivity.class);
						break;
				}

				if (((CheckBox)findViewById(R.id.login_save_credentials)).isChecked()) {
					preferences.edit().putBoolean("pref_key_login_save_credentials", true).apply();
					preferences.edit().putString("pref_key_login_user", 
						((EditText)findViewById(R.id.login_login_user_box)).getEditableText().toString()).apply();
					preferences.edit().putString("pref_key_login_pwd", 
						((EditText)findViewById(R.id.login_login_pass_box)).getEditableText().toString()).apply();
				}

				next.putExtra("de.akabahn.ebd.control.userName", user.getUsername());
				next.putExtra("de.akabahn.ebd.control.roleName", user.getAccessRights().name());
				if (posNummer != -1) {
					next.putExtra("de.akabahn.ebd.control.bhf", bahnhof.substring(posNummer));
				}
				startActivity(next);
			}
		});
		
		CheckBox saveCredentials = (CheckBox) findViewById(R.id.login_save_credentials);
		saveCredentials.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				if (!((CheckBox)v).isChecked()) {
					((EditText) findViewById(R.id.login_login_pass_box)).setText("");
					((EditText) findViewById(R.id.login_login_user_box)).setText("");
					((EditText) findViewById(R.id.login_login_user_box)).requestFocus();
					preferences.edit().putBoolean("pref_key_login_save_credentials", false).apply();
					preferences.edit().putString("pref_key_login_user", null).apply();
					preferences.edit().putString("pref_key_login_pwd", null).apply();
				}
			}
		});
	}

	@Override
	public void onStart() {
		super.onStart();

		if (preferences.getBoolean("pref_key_login_save_credentials", false)) {
			((EditText) findViewById(R.id.login_login_pass_box)).setText(preferences.getString("pref_key_login_pwd", null));
			((EditText) findViewById(R.id.login_login_user_box)).setText(preferences.getString("pref_key_login_user", null));
			((CheckBox)findViewById(R.id.login_save_credentials)).setChecked(true);
		} else {
			((EditText) findViewById(R.id.login_login_pass_box)).setText("");
			((EditText) findViewById(R.id.login_login_user_box)).setText("");
			((EditText) findViewById(R.id.login_login_user_box)).requestFocus();
		}		

		String errorMessage = getIntent().getStringExtra("de.akabahn.ebd.control.errormessage");
		TextView errorMessageView = (TextView)findViewById(R.id.login_errorMessage);
		if (errorMessage != null) {
			errorMessageView.setTextColor(Color.RED);
			errorMessageView.setText(getResources().getString(R.string.login_errorMessageText, errorMessage));
			getIntent().putExtra("de.akabahn.ebd.control.errormessage", (String)null);
		} else {
			errorMessageView.setText("");
		}

		String stackTrace = getIntent().getStringExtra("de.akabahn.ebd.control.stacktrace");
		TextView stackTraceView = (TextView)findViewById(R.id.login_stackTrace);
		if (stackTrace != null) {
			stackTraceView.setTextColor(Color.GRAY);
			stackTraceView.setText(getResources().getString(R.string.login_stackTraceText, stackTrace));
			getIntent().putExtra("de.akabahn.ebd.control.stacktrace", (String)null);
		} else {
			stackTraceView.setText("");
		}
    }

	private UserAuthObject checkCredentials() {
		String username = ((EditText)findViewById(R.id.login_login_user_box)).getEditableText().toString();
		String password = ((EditText)findViewById(R.id.login_login_pass_box)).getEditableText().toString();

		if (username != null && username.startsWith("ost18wind_")) {
			authenticator = StaticAuthenticator.getInstance();
			username = username.substring(username.indexOf('_') + 1);
		} else {
			authenticator = RemoteAuthenticator.getInstance();
		}

		return authenticator.authenticateUser(username, password);
	}
	
	private int getVersionAsNumber(String versionAsString) {
		return Integer.parseInt(versionAsString.replace('.', '0'));
	}
}